home *** CD-ROM | disk | FTP | other *** search
/ .net (French) 1996 December / .net Magazine (FR) - Issue 02 - Dec 1996.iso / Utilpers / SUPERQUE / DATA.2 / FILTERS / PSINIT / GS_SETPD.PS < prev    next >
Text File  |  1996-01-05  |  10KB  |  324 lines

  1. %    Copyright (C) 1994, 1995 Aladdin Enterprises.  All rights reserved.
  2. %    Licensed to Zenographics Inc. (Irvine, California) by Artifex Software Inc.
  3. %    under the OEM Agreement of December 21st, 1993.
  4.  
  5. % The current implementation of setpagedevice has the following problems:
  6. %    - It doesn't save the CTM after the Install procedure as the
  7. % one for initmatrix or defaultmatrix.
  8. %    - It doesn't interact properly with gsave/grestore.
  9. %    - It doesn't do the automatic 90 degree rotation if the PageSize
  10. % dimensions need to be swapped.
  11. %    - It doesn't handle Policy values other than 1 or non-1.
  12.  
  13. languagelevel 1 .setlanguagelevel
  14. level2dict begin
  15.  
  16. % Define currentpagedevice so it creates the dictionary on demand if needed.
  17. % The only entry we add automatically is Policies.
  18. /currentpagedevice
  19.  { .currentpagedevice dup length 0 eq
  20.     { pop currentdevice null .getdeviceparams
  21.         % In case of duplicate keys, .dicttomark takes the entry
  22.         % lower on the stack, so we can just append the defaults here.
  23.       /Policies .defaultpolicies .dicttomark
  24.       dup .setpagedevice
  25.     }
  26.    if
  27.  } bind odef
  28.  
  29. % The implementation of setpagedevice is quite complex.  Currently,
  30. % everything but the media matching algorithm is implemented here.
  31.  
  32. % Define the parameters that require special action to merge into the
  33. % combined page device dictionary.  The procedures are called as follows:
  34. %    <merged> <key> <new_value> -proc- <merged> <key> <new_value'>
  35. /.mergespecial mark
  36.   /InputAttributes
  37.    { dup null eq
  38.       { pop null
  39.       }
  40.       { 3 copy pop .knownget
  41.      { dup null eq
  42.         { pop dup length dict }
  43.         { dup length 2 index length add dict copy }
  44.        ifelse
  45.      }
  46.      { dup length dict
  47.      }
  48.         ifelse copy readonly
  49.       }
  50.      ifelse
  51.    } bind
  52.   /OutputAttributes 1 index
  53.   /Policies
  54.     { 3 copy pop .knownget
  55.        { dup length 2 index length add dict copy }
  56.        { dup length dict }
  57.       ifelse copy readonly
  58.     } bind
  59. .dicttomark readonly def
  60.  
  61. % Define the keys used in input attribute matching.
  62. /.inputattrkeys [
  63.   /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet
  64. ] readonly def
  65.  
  66. % Define the keys used in output attribute matching.
  67. /.outputattrkeys [
  68.   /OutputType
  69. ] readonly def
  70.  
  71. % Define the parameters that should not be presented to the device.
  72. % The procedures are called as follows:
  73. %    <merged> <key> <value> -proc-
  74. % The procedure leaves all its operands on the stack and returns
  75. % true iff the key/value pair should be presented to .putdeviceparams.
  76. /.presentspecial mark
  77.   /Name false
  78.   /OutputDevice false
  79.   /InputAttributes false
  80.   .inputattrkeys { pop { 2 index /InputAttributes get null eq } } forall
  81.   /OutputAttributes false
  82.   .outputattrkeys { pop { 2 index /OutputAttributes get null eq } } forall
  83.   /Install false
  84.   /BeginPage false
  85.   /EndPage false
  86.   /Policies false
  87. .dicttomark readonly def
  88.  
  89. % Define the required attributes of all page devices, and their default values.
  90. % We don't include attributes such as PageSize, which all devices
  91. % are guaranteed to supply on their own.
  92. /.defaultpolicies mark
  93.   /PolicyNotFound 1
  94.   /PageSize 0
  95.   /PolicyReport {pop} bind
  96. .dicttomark readonly def
  97. /.requiredattrs mark
  98.   /InputAttributes mark 0 0 dict .dicttomark
  99.   /OutputAttributes mark 0 0 dict .dicttomark
  100.   /Install {.callinstall} bind
  101.   /BeginPage {.callbeginpage} bind
  102.   /EndPage {.callendpage} bind
  103.   /Policies .defaultpolicies
  104. .dicttomark readonly def
  105.  
  106. % Define access to device defaults.
  107. /.defaultdevicename 0 .getdevice .devicename def
  108. /.defaultdeviceparams
  109.  { finddevice null .getdeviceparams
  110.  } bind def
  111.  
  112. % Select media (input or output).  The hard work is done in an operator:
  113. %    <pagedict> <attrdict> <keys> .matchmedia <key> true
  114. %    <pagedict> <attrdict> <keys> .matchmedia false
  115. %    <pagedict> null <keys> .matchmedia null true
  116. /.selectmedia        % <orig> <request> <merged> <failed>
  117.             %   (these are retained)
  118.             %   <attrdict> <attrkeys> <mediakey> .selectmedia
  119.  { 4 index 4 -1 roll 3 index .matchmedia
  120.     { 4 index 3 1 roll put pop
  121.     }
  122.     {    % Adobe's implementations have a "big hairy heuristic"
  123.     % to choose the set of keys to report as having failed the match.
  124.     % For the moment, we report any keys that are in the request
  125.     % and don't have the same value as in the original dictionary.
  126.       3 index exch undef
  127.        {    % Stack: <orig> <request> <merged> <failed> <attrkey>
  128.      3 index 1 index .knownget
  129.       { 5 index 2 index .knownget { ne } { pop true } ifelse }
  130.       { true }
  131.      ifelse        % Stack: ... <failed> <attrkey> <report>
  132.       { 2 copy /rangecheck put }
  133.      if pop
  134.        }
  135.       forall
  136.     }
  137.    ifelse
  138.  } bind def
  139.  
  140. % Apply Policies to any unprocessed failed requests.
  141. % As we process each request entry, we replace the error name
  142. % in the <failed> dictionary with the policy value,
  143. % and we remove the key from the <merged> dictionary.
  144. /.applypolicies        % <merged> <failed> .applypolicies <merged'> <failed'>
  145.  { 1 index /Policies get 1 index
  146.     { type /integertype eq
  147.        { pop        % already processed
  148.        }
  149.        { 2 copy .knownget not { 1 index /PolicyNotFound get } if
  150.             % Stack: <merged> <failed> <Policies> <key> <policy>
  151.      dup 1 ne
  152.       {    % Set errorinfo and signal a configurationerror.
  153.         % Note that we currently treat all Policy values other than 1
  154.         % the same as 0.
  155.         pop dup 4 index exch get 2 array astore
  156.         $error /errorinfo 3 -1 roll put
  157.         cleartomark
  158.         /setpagedevice load /configurationerror signalerror
  159.       }
  160.       {    % Ignore the failed request.
  161.         3 index 2 index 3 -1 roll put
  162.         3 index exch undef
  163.       }
  164.      ifelse
  165.        }
  166.       ifelse
  167.     }
  168.    forall pop
  169.  } bind def
  170.  
  171. % Try setting the device parameters from the merged request.
  172. /.trysetparams        % ... <merged> <(ignored)> <device> <Policies>
  173.             %   .trysetparams
  174.  { true mark 5 index dup
  175.     {            % Stack: <merged> <key> <value>
  176.       .presentspecial 2 index .knownget
  177.        { exec { 3 -1 roll } { pop pop } ifelse }
  178.        { 3 -1 roll }
  179.       ifelse
  180.     }
  181.    forall pop
  182. DEBUG { (Putting.\n) print pstack flush } if
  183.    .putdeviceparams
  184. DEBUG { (Result of putting.\n) print pstack flush } if
  185.  } bind def
  186.  
  187. % Finally, define setpagedevice.
  188. /setpagedevice
  189.  {
  190.    mark exch currentpagedevice
  191.  
  192.         % Check whether we are changing OutputDevice;
  193.         % also handle the case where the current device
  194.         % is not a page device.
  195.         % Stack: mark <request> <current>
  196. DEBUG { (Checking.\n) print pstack flush } if
  197.  
  198.    dup /OutputDevice .knownget
  199.     {        % Current device is a page device.
  200.       2 index /OutputDevice .knownget
  201.        {    % A specific OutputDevice was requested.
  202.      2 copy eq
  203.       { pop pop null }
  204.       { exch pop }
  205.      ifelse
  206.        }
  207.        { pop null
  208.        }
  209.       ifelse
  210.     }
  211.     {        % Current device is not a page device.
  212.         % Use the default device.
  213.       1 index /OutputDevice .knownget not { .defaultdevicename } if
  214.     }
  215.    ifelse
  216.    dup null eq
  217.     { pop
  218.     }
  219.     { exch pop .defaultdeviceparams
  220.         % In case of duplicate keys, .dicttomark takes the entry
  221.         % lower on the stack, so we can just append the defaults here.
  222.       .requiredattrs { } forall .dicttomark
  223.     }
  224.    ifelse
  225.  
  226.         % Merge the current and requested dictionaries.
  227.         % Stack: mark <request> <orig>
  228. DEBUG { (Merging.\n) print pstack flush } if
  229.  
  230.    exch 1 index dup length 2 index length add dict copy
  231.    dup 2 index
  232.     {        % stack: <orig> <request> <merged> <merged> <rkey> <rvalue>
  233.       .mergespecial 2 index .knownget { exec } if
  234.       put dup
  235.     }
  236.    forall pop
  237.  
  238.         % Select input and output media.
  239.         % Stack: mark <orig> <request> <merged>
  240. DEBUG { (Selecting.\n) print pstack flush } if
  241.  
  242.    0 dict    % <failed>
  243.    1 index /InputAttributes .knownget
  244.     { .inputattrkeys (%MediaSource) cvn .selectmedia } if
  245.    1 index /OutputAttributes .knownget
  246.     { .outputattrkeys (%MediaDestination) cvn .selectmedia } if
  247.    .applypolicies
  248.  
  249.         % Construct the new device, and attempt to set its attributes.
  250.         % Stack: mark <orig> <request> <merged> <failed>
  251. DEBUG { (Constructing.\n) print pstack flush } if
  252.  
  253.    currentdevice .devicename 2 index /OutputDevice get eq
  254.     { currentdevice }
  255.     { 1 index /OutputDevice get finddevice }
  256.    ifelse
  257.         %**************** We should copy the device here,
  258.         %**************** but since we can't close the old device,
  259.         %**************** we don't.  This is WRONG.
  260.     %****************copydevice
  261.    2 index /Policies get
  262.    .trysetparams
  263.    dup type /nametype eq
  264.     {        % The request failed.
  265.         % Stack: ... <failed> <device> <Policies> true mark
  266.         %   <name> <errorname> ...
  267.       counttomark 5 add -1 roll
  268.       counttomark 2 idiv { dup 4 -2 roll put } repeat
  269.       exch pop 4 1 roll pop
  270.         % Stack: mark ... <merged> <failed> <device> <Policies>
  271.       4 2 roll .applypolicies 4 -2 roll
  272.       .trysetparams        % shouldn't fail, except for /undefined
  273.       % Remove /undefined's
  274.       dup type /nametype eq
  275.        {        % The request failed.
  276.            % Stack: ... <failed> <device> <Policies> true mark
  277.            %   <name> <errorname> ...
  278.          counttomark 5 add -1 roll
  279.          counttomark 2 idiv { dup 4 -2 roll put } repeat
  280.          exch pop 4 1 roll pop
  281.            % Stack: mark ... <merged> <failed> <device> <Policies>
  282.          4 2 roll .applypolicies 4 -2 roll
  283.          .trysetparams        % shouldn't fail
  284.        }
  285.       if
  286.       dup type /booleantype ne
  287.        { 2 { counttomark 1 add 1 roll cleartomark } repeat
  288.          /setpagedevice load exch signalerror
  289.        }
  290.       if
  291.     }
  292.    if
  293.  
  294.         % The attempt succeeded.  Install the new device.
  295.         % Stack: mark ... <merged> <failed> <device> <eraseflag>
  296. DEBUG { (Installing.\n) print pstack flush } if
  297.    pop 2 .endpage
  298.     { 1 true .outputpage
  299. %      (>>setpagedevice, press <return> to continue<<\n) .confirm
  300.     }
  301.    if
  302.    .setdevice pop
  303.    1 index /Install .knownget { exec } if
  304.    erasepage initgraphics
  305.    1 index .setpagedevice .beginpage
  306.  
  307.         % Clean up, calling PolicyReport if needed.
  308.         % Stack: mark ... <merged> <failed>
  309. DEBUG { (Finishing.\n) print pstack flush } if
  310.  
  311.    dup length 0 ne
  312.     { 1 index /Policies get /PolicyReport get
  313.       counttomark 1 add 2 roll cleartomark
  314.       exec
  315.     }
  316.     { cleartomark
  317.     }
  318.    ifelse
  319.  
  320.  } odef
  321.  
  322. end                % level2dict
  323. .setlanguagelevel
  324.